import { convertFormData, getAggFnList, getNormalFnList, isEmpty } from '@/utils/util';
import { EMIT_PARAMS_OBJ } from '@/utils/constant';

export default {
  methods: {

    // 巨大函数切分优化
    _getHasFnAndName(aggFnList, normalFnList, item) {
      // 是否包含聚合函数字段
      let hasFn = false;
      let fnName = '';

      aggFnList.forEach(name => {
        if (!hasFn && item.mapping.includes(`${name}(`)) {
          hasFn = true;
          fnName = name;
        }
      });

      // 处理普通函数
      let hasNormalFn = false;
      normalFnList.forEach(name => {
        if (!hasNormalFn && (item.mapping.includes(`${name}(`) || item.mapping.startsWith('['))) {
          hasNormalFn = true;
        }
      });
      return { hasFn, fnName, hasNormalFn };
    },

    // 获取xTag格式的参数
    getParamsXTag(data) {
      const params = {
        ...this.params,
        propertyMapping: convertFormData(data.tableData), // 配置页面中 选择的呈现字段
      };
      const aggFnList = getAggFnList(); // 聚合函数列表
      const normalFnList = getNormalFnList();

      // 初始化配置
      let isFirstAgg = true;
      let isFirstCustomFields = true;
      delete params.apiCode;
      delete params.params;
      delete params.agg;
      delete params.customFields;

      data.tableData.forEach(item => {
        const { hasFn, fnName, hasNormalFn } = this._getHasFnAndName(aggFnList, normalFnList, item);

        // 判断是否自定义计算字段
        if (item.type || fnName) {
          // 自定义计算字段中有函数时的处理方式
          if (hasFn) {
            // 初始化 agg 字段
            if (isFirstAgg) {
              isFirstAgg = false;
              params.agg = {
                aggregateObjs: [],
              };
            }

            // 目前只能处理单函数 单参数 ,目前匹配第一个函数，第一个中括号的内容
            const reg = /\[(.+?)\]/g;
            const fields = item.mapping.match(reg);
            const field = fields.length ? fields[0] : '';
            params.agg.aggregateObjs.push({ alias: item.mapping, field: field, aggregator: fnName });
          }
          if (hasNormalFn) {
            // 初始化 customFields 字段 插入普通函数参数
            if (isFirstCustomFields) {
              isFirstCustomFields = false;
              params.customFields = [];
            }
            params.customFields.push({ fieldsName: item.mapping, function: item.mapping });
          }
        }
      });
      return params;
    },

    updateParamsxTag(obj) {
      this.updateParamsxTagCheck();

      // 删除已删发出组件的参数
      const { wid } = this.needClearOutEvent;
      if (this.params.conditions && wid) {
        this.params.conditions = this.params.conditions.filter(n => n.wid !== wid);
      }

      for (const key in obj) {
        if (key.indexOf(EMIT_PARAMS_OBJ) <= -1) {
          continue;
        }

        const hasEvent = this.config.events.find(n => n.type === 'in' && n.key === obj[key].eventKey);
        if (hasEvent) {
          this.addReceivedEvents(obj[key], 'normal');
        }

        // 参数值存放在EMIT_PARAMS_OBJ内部，不放在外部，实验性方案，触发参考slide-fitler组件
        const updateRes = this.updateParamsByWid(
          {
            [key]: obj[key],
          },
          'xTag',
          this.params,
        );
        if (updateRes) {
          continue;
        }

        const paramObj = obj[key];
        const { eventKey } = paramObj;
        const paramKey = paramObj.key;
        const value = obj[paramKey];

        // 遍历config 查看配置的事件
        let flag = false;
        this.config.events.forEach(event => {
          if (event.type === 'in' && String(event.key) === String(eventKey)) {
            flag = true;
            this.updateParamsXTagSqlParams(this.params.sqlParams, obj, key);
          }
        });
        if (!flag) {
          continue;
        }

        // 特殊情况，时间组件为范围值
        if (paramObj.type === 'range') {
          // 用空值对象清除当前params conditions
          this.checkConditionsType('range');
          this.checkConditionsType('terms');
          this.updateParamsXTagConditions('', 'range', paramKey);
          this.updateParamsXTagConditions('', 'terms', paramKey);
          this.updateParamsXTagConditionsRange({
            paramObj,
            paramKey,
            value,
            obj,
          });
        } else {
          this.checkConditionsType(paramObj.type);
          this.updateParamsXTagConditions(value, paramObj.type, paramKey);
        }
      }
    },
    updateParamsXTagSqlParams(target, obj, key) {
      const paramObj = obj[key];
      const paramKey = paramObj.key;
      let value = obj[paramKey];

      // 特殊情况 时间有可能有2个key
      const paramKey2 = paramObj.key_endTime;
      const value2 = obj[paramKey2];
      if (!Array.isArray(value)) {
        value = [value];
      }
      const paramItem = {
        key: paramKey,
        value: value,
      };
      const paramIndex = target.findIndex(p => String(p.key) === String(paramKey));

      // 不存在
      if (paramIndex === -1) {
        if (!isEmpty(value)) {
          target.push(paramItem);
        }
      } else {
        // 存在，但为空值，从target中移除
        if (isEmpty(value)) {
          target.splice(paramIndex, 1);
        } else {
          target.splice(paramIndex, 1, paramItem);
        }
      }

      // 特殊情况 时间有可能有2个key
      if (paramKey2) {
        const param2 = target.find(p => String(p.key) === String(paramKey2));
        if (param2) {
          param2.value = value2 ? value2 : param2.value;
        } else {
          if (value2) {
            target.push({
              key: paramKey2,
              value: value2,
            });
          }
        }
      } else {
        // 当且仅当时间筛选组件时间范围切换时间点场景才删除值
        const timeOption = paramObj.option;
        if (!timeOption) {
          return;
        }
        const endPram = target.find(p => String(p.key) === String(timeOption.key_endTime));
        if (endPram) {
          const index = target.indexOf(endPram);
          target.splice(index, 1);
        }
      }
    },

    // 检查xtag参数对象
    updateParamsxTagCheck() {
      if (!this.params.conditions) {
        this.params.conditions = [{}];
      }
      if (!this.params.sqlParams) {
        this.params.sqlParams = [];
      }
    },
    updateParamsXTagConditions(value, type, paramKey) {
      let itemIndex;
      let item;

      // 找到同名的参数
      this.params.conditions[0][type].forEach((paramsConditionObj, index) => {
        const keys = Object.keys(paramsConditionObj);
        if (keys.includes(paramKey)) {
          item = paramsConditionObj;
          itemIndex = index;
        }
      });

      // 空值的情况 删除该过滤条件
      if (isEmpty(value)) {
        if (item) {
          this.params.conditions[0][type].splice(itemIndex, 1);
        }
      } else {
        // 用 [] 包装值
        let _value;
        if (!Array.isArray(value)) {
          _value = [value];
        }
        if (item) {
          item[paramKey] = _value;
        } else {
          this.params.conditions[0][type].push({
            [paramKey]: _value,
          });
        }
      }
    },
    updateParamsXTagConditionsRange({ paramObj, paramKey, value, obj }) {
      // 时间组件的结束时间
      const paramKeyEndTime = paramObj.key_endTime;
      const valueEndTime = obj[paramKeyEndTime];
      const type = valueEndTime ? 'range' : 'terms';
      const item = this.params.conditions[0][type].find(i => {
        const keys = Object.keys(i);
        return keys.includes(paramKey);
      });

      if (item) {
        if (valueEndTime) {
          item[paramKey] = {
            gte: value,
            lte: valueEndTime,
          };
        } else {
          item[paramKey] = [value];
        }
      } else {
        if (valueEndTime) {
          this.params.conditions[0][type].push({
            [paramKey]: {
              gte: value,
              lte: valueEndTime,
            },
          });
        } else {
          this.params.conditions[0][type].push({
            [paramKey]: [value],
          });
        }
      }
    },

    // 检查xtag参数对象 conditions[0][type]  type: 'range' : 'terms'
    checkConditionsType(type) {
      if (!this.params.conditions[0][type]) {
        this.params.conditions[0][type] = [];
      }
    },

    _dealConditionItem(params) {
      const { dict, item, type, conditions, index } = params;
      let _index = index;
      const subItem = item[type][0];
      for (const k in subItem) {
        if (dict[type][k]) {
          conditions.splice(index, 1);
          _index--;
        } else {
          dict[type][k] = 1;
          const x = type === 'terms' ? subItem[k][0] : subItem[k];

          // 如果为空，则移除
          if (isEmpty(x)) {
            conditions.splice(index, 1);
            _index--;
          }
        }
      }
      return _index;
    },

    _reviseParamsxTagConditions(conditions) {
      const dict = { terms: {}, match: {}, range: {} }; // 记录出现过的key
      conditions.reverse();

      for (let index = 0; index < conditions.length; index++) {
        const item = conditions[index];
        if (!item.wid) {
          continue;
        }

        if (item.terms && item.terms.length) {
          index = this._dealConditionItem({ dict, item, type: 'terms', conditions, index });
        }
        if (item.match && item.match.length) {
          index = this._dealConditionItem({ dict, item, type: 'match', conditions, index });
        }
        if (item.range && item.range.length) {
          const subItem = item.range[0];
          for (const k in subItem) {
            if (dict.range[k]) {
              conditions.splice(index, 1);
              index--;
            } else {
              dict.range[k] = 1;
            }
          }
        }
      }
      conditions.reverse();
    },

    _reviseParamsxTagSqlParams(sqlParams) {
      sqlParams.reverse();
      const dict = {}; // 记录出现过的key
      for (let index = 0; index < sqlParams.length; index++) {
        const item = sqlParams[index];
        if (item.wid) {
          if (dict[item.key]) {
            sqlParams.splice(index, 1);
            index--;
          } else {
            dict[item.key] = 1;

            // 如果为空，则移除
            if (isEmpty(item.value)) {
              sqlParams.splice(index, 1);
              index--;
            }
          }
        }
      }
      sqlParams.reverse();
    },

    // 修正参数
    reviseParamsxTag(curParams) {
      const _params = JSON.parse(JSON.stringify(curParams));

      // 删除有可能出现的xMiner参数（编排端切换数据源）
      delete _params.params;

      const { conditions } = _params;
      const { sqlParams } = _params;
      if (conditions && conditions.length) {
        this._reviseParamsxTagConditions(conditions);
      }
      if (sqlParams && sqlParams.length) {
        this._reviseParamsxTagSqlParams(sqlParams);
      }
      return _params;
    },
  },
};
